from datetime import datetime, timedelta, date

import numpy as np
import pandas as pd
from sklearn import preprocessing
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier

from quant import data_utils

total_ev = 0
total_bet = 0


def prepare_data():
    # 预处理数据
    df = pd.read_csv("d3.csv", encoding="UTF-8",
                     usecols=["比赛时间", "联赛", "胜临", "平临", "负临", "让胜临", "让平临", "让负临", "让球", "赛果",
                              "让球赛果"],
                     header=0,
                     low_memory=False)
    df = df.dropna()

    start_date = "2023-01-01"
    end_date = "2024-07-01"
    league = "英超"

    df['比赛时间'] = pd.to_datetime(df['比赛时间'])
    df = df[(df['比赛时间'] >= start_date) & (df['比赛时间'] <= end_date)]
    if league != "":
        df = df[df['联赛'] == league]

    df['赛果'] = df['赛果'].apply(lambda x: 2 if x == "胜" else x)
    df['赛果'] = df['赛果'].apply(lambda x: 1 if x == "平" else x)
    df['赛果'] = df['赛果'].apply(lambda x: 0 if x == "负" else x)

    df['让球赛果'] = df['让球赛果'].apply(lambda x: 2 if x == "胜" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 1 if x == "平" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 0 if x == "负" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 2 if x == "让胜" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 1 if x == "让平" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 0 if x == "让负" else x)

    X = df.drop(["赛果", "让球赛果", "比赛时间", "联赛"], axis=1)
    y = df["赛果"]
    # y = df["让球赛果"]
    return X, y


def read_test_data(day=0):
    matches = data_utils.read_matches(day)
    if not matches:
        return None, None, None
    data = {
        '让球': [],
        '胜临': [],
        '平临': [],
        '负临': [],
        '让胜临': [],
        '让平临': [],
        '让负临': [],
        '赛果': [],
        '让球赛果': [],
        'teams': []
    }
    for m in matches.values():
        data["让球"].append(int(m.rangqiu))
        data["胜临"].append(float(m.win))
        data["平临"].append(float(m.draw))
        data["负临"].append(float(m.lose))
        data["让胜临"].append(float(m.rangqiu_win))
        data["让平临"].append(float(m.rangqiu_draw))
        data["让负临"].append(float(m.rangqiu_lose))
        data["赛果"].append(m.result)
        data["让球赛果"].append(m.rangqiu_result)
        data["teams"].append(f"{m.home_team}vs{m.away_team}")

    df = pd.DataFrame(data)
    df['赛果'] = df['赛果'].apply(lambda x: 2 if x == "3" else x)
    df['赛果'] = df['赛果'].apply(lambda x: 1 if x == "1" else x)
    df['赛果'] = df['赛果'].apply(lambda x: 0 if x == "0" else x)

    df['让球赛果'] = df['让球赛果'].apply(lambda x: 2 if x == "3" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 1 if x == "1" else x)
    df['让球赛果'] = df['让球赛果'].apply(lambda x: 0 if x == "0" else x)
    X = df.drop(["赛果", "teams", "让球赛果"], axis=1)
    y = df[("赛果")]
    # y = df[("让球赛果")]
    teams = df[("teams")].astype(str)

    return X, y, teams


def getClassifier():
    classifier = GaussianNB()
    return classifier


def run():
    days = 30
    for i in range(-1, -days, -1):
        run_once(i)


def run_once(day=0):
    dt = (datetime.now() + timedelta(days=day)).strftime('%Y-%m-%d')
    X, y = prepare_data()
    x_true, y_true, teams = read_test_data(day)
    if x_true is None:
        print(f"********** day:{day} dt:{dt} 无比赛")
        return

    y_rangqiu = []
    for i in range(len(x_true)):
        # 处理每一行的数据
        rangqiu = x_true.iloc[i]['让球']
        if (rangqiu > 0):
            y_rangqiu.append(0)
        else:
            y_rangqiu.append(2)

    classifier = getClassifier()
    classifier.fit(X, y)
    y_pred = classifier.predict(x_true)
    score = accuracy_score(y_true, y_pred)
    rangqiu_score = accuracy_score(y_rangqiu, y_pred)
    bonus = 0
    for i in range(len(x_true)):
        if (y_pred[i] == y_true.values[i]):
            match_bonus = 0
            if y_pred[i] == 0:
                match_bonus = x_true.iloc[i]["负临"]
            elif y_pred[i] == 1:
                match_bonus = x_true.iloc[i]["平临"]
            else:
                match_bonus = x_true.iloc[i]["胜临"]
            bonus += match_bonus
    ev = round(bonus - len(x_true), 2)
    global total_ev, total_bet
    total_ev += ev
    total_bet += len(x_true)
    # print(
    #     f"********** day:{day} dt:{dt} total_ev:{round(total_ev, 2)} total_bet:{total_bet} ev:{ev} count:{len(x_true)} bonus:{bonus} score:{round(score, 2)} 让球score:{round(rangqiu_score, 2)} **********\n"
    #     f"y_true:{y_true.values} y_pred:{y_pred}\n"
    # )

    print(
        f"********** day:{day} dt:{dt} total_ev:{round(total_ev, 2)} total_bet:{total_bet} ev:{ev} count:{len(x_true)} bonus:{round(bonus, 2)} score:{round(score, 2)} 让球score:{round(rangqiu_score, 2)} **********\n"
        f"y_true:{y_true.values} y_pred:{y_pred}")


def predict_half():
    day = 0
    matches = data_utils.read_matches(day)
    home_conditions = [
        {"low": 1.2, "high": 1.4, "half": "负胜"},
        {"low": 1.6, "high": 1.8, "half": "平平"},
        {"low": 1.6, "high": 1.8, "half": "负平"},
        {"low": 1.8, "high": 2, "half": "负胜"},
        {"low": 2, "high": 2.2, "half": "负平"},
    ]

    away_conditions = [
        {"low": 2, "high": 2.2, "half": "负平"},
        {"low": 2.4, "high": 2.6, "half": "胜平"},
    ]

    options=[]
    for m in matches.values():
        win = float(m.win)
        lose = float(m.lose)
        print(f"{m.no} {m.home_team} vs {m.away_team} {m.win} {m.draw} {m.lose}")
        for c in home_conditions:
            if c["low"] <= win <= c["high"]:
                options.append({"no":f"{m.no} {m.home_team} vs {m.away_team}","option":c["half"]})
        pass

        for c in away_conditions:
            if c["low"] <= lose <= c["high"]:
                options.append({"no": f"{m.no} {m.home_team} vs {m.away_team}", "option": c["half"]})
        pass
    pass

    for option in options:
        print(f"{option['no']} {option['option']}")


if __name__ == '__main__':
    # run()
    # run_once(-3)
    predict_half()
